package com.qf.chinatelcon.apigateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qf.chinatelcon.apigateway.cache.GrayReleaseLocalCache;
import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;

@Component
public class GrayReleaseFilter extends ZuulFilter {
    //我现在想要根据流量进行切换，你访问那个版本都可以获取到数据，但是我要慢慢的切换到新版本
    //我们需要在某个需要的配置里保存着灰度的接口,比如表示多少比例或者多少次
    //我们需要10以上的接口切换到新版其他剩余的都还在老版本里


    private GrayReleaseLocalCache grayReleaseLocalCache;

    @Autowired
    public void setGrayReleaseLocalCache(GrayReleaseLocalCache grayReleaseLocalCache) {
        this.grayReleaseLocalCache = grayReleaseLocalCache;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1000;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        boolean zuulResponse = context.sendZuulResponse();
        Object o = context.get(FilterConstants.SERVICE_ID_KEY);//获取到要转发的服务的名字
        Object yuanshidizhi = context.get("yuanshidizhi");//获取到原始地址，为了避免那种rest风格的找不到地址,因为我们转发的地址，是不带参数化的地址
        //当前访问的地址处于灰度发布列表中才会放行
        List<Map> grayConfig = grayReleaseLocalCache.getGrayConfig(o + "" + yuanshidizhi);//去缓存中查找是否存在
        if (grayConfig == null || grayConfig.size() == 0) {
            //没有规则就返回false
            return false;
        }
        context.put("grayguize", grayConfig);//保存规则，目的是为了在下边方便使用
        context.put("path", o + "" + yuanshidizhi);//保存请求的路径
        return zuulResponse;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        //根据地址获取到现在所适用的规则,比如123各自还剩下多少
        String path = context.get("path") + "";//正在访问的路径
        List<String> usedConfig = grayReleaseLocalCache.getUsedConfig(path);//根据路径获取到正在使用的规则
        //如果没有了就重新放进去一次
        if (usedConfig == null || usedConfig.size() == 0) {
            List<Map> grayguize = (List<Map>) context.get("grayguize");//
            grayguize.forEach(map -> {
                Integer percent = (Integer) map.get("percent");//获取到次数
                String forward = (String) map.get("forward");//获取到请求的服务的表示
                for (Integer i = 0; i < percent; i++) {
                    grayReleaseLocalCache.add2Config(path, forward);//保存规则
                }

            });
        }
        usedConfig = grayReleaseLocalCache.getUsedConfig(path);//重新获取一次规则
        Collections.shuffle(usedConfig);
        String forwardvalue = usedConfig.remove(0);//我们总是移除下标为0的数据,获取到要访问的服务的标识

        RibbonFilterContextHolder.getCurrentContext().add("forward", forwardvalue);//添加要访问服务的标识，定义在metadata-map中，实现灰度发布

        return null;
    }
}
